/***************************************************************************
 *   oboe.math.Rotator                                                     *
 *   Copyright (C) 2011 by Felipe Manga                                    *
 *   lufeboma@gmail.com                                                    *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

package oboe.math
{
	/**
	 * This class is for rotating various 3D points on the X/Y/Z axis. 
	 * @author FelipeManga
	 * 
	 */
	public class Rotator extends Number3D
	{
		public var xvx : Number;
		public var xvy : Number;
		public var xvz : Number;
		public var yvx : Number;
		public var yvy : Number;
		public var yvz : Number;
		public var zvx : Number;
		public var zvy : Number;
		public var zvz : Number;
		
		/**
		 * Class cosntructor 
		 * @param x initial X axis rotation in radians
		 * @param y initial Y axis rotation in radians
		 * @param z initial Z axis rotation in radians
		 * 
		 */
		public function Rotator(x:Number, y:Number, z:Number)
		{
			super(x, y, z);
			this.update();
		}
		
		/**
		 * Before calling the apply functions, the rotator must be updated if the X, Y or Z angle has changed. 
		 */
		public function update() : void {
			this.mod( 6.283185 );
			
			var cosxr : Number, cosyr : Number, coszr : Number, sinxr : Number, sinyr : Number, sinzr : Number;
			cosxr = Math.cos(x); cosyr = Math.cos(y); coszr = Math.cos(z);
			sinxr = Math.sin(x); sinyr = Math.sin(y); sinzr = Math.sin(z);

			xvx = (cosyr * coszr); xvy = (sinxr * sinyr * coszr - cosxr * sinzr); xvz = (cosxr * sinyr * coszr + sinxr * sinzr);
			yvx = (cosyr * sinzr); yvy = (cosxr * coszr + sinxr * sinyr * sinzr); yvz = (-sinxr * coszr + cosxr * sinyr * sinzr);
			zvx = (-sinyr); zvy = (sinxr * cosyr); zvz = (cosxr * cosyr);
		}
		
		/**
		 * Applies a rotation without modifying the input vector 
		 * @param vec input vector
		 * @param out output vector
		 * 
		 */
		public function constapply( vec : Number3D, out : Number3D ) : void {
			out.x = vec.x * xvx + vec.y * xvy + vec.z * xvz;
			out.y = vec.x * yvx + vec.y * yvy + vec.z * yvz;
			out.z = vec.x * zvx + vec.y * zvy + vec.z * zvz;
		}	
		
		/**
		 * Applies a rotation to a vector 
		 * @param vec vector to rotate
		 * 
		 */
		public function apply( vec : Number3D ) : void {
			vec.copy2( 
				vec.x * xvx + vec.y * xvy + vec.z * xvz, 
				vec.x * yvx + vec.y * yvy + vec.z * yvz,
				vec.x * zvx + vec.y * zvy + vec.z * zvz
			);
		}
	}
}